package com.emmmya.ocs.common.utils.httpClient;

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 依赖方法封装
 * 基本的http请求抽象类
 * @author chengxi
 * @date 2020/5/30 21:00
 */
@Slf4j
public abstract class AbstractExtractionRestUtil {

    /**
     * 抽取请求bean
     *
     * @param appId
     * @param apiUrl
     * @param requestData
     * @param responseBeanClass
     * @param restTemplate
     * @param httpMethod
     * @param <T>
     * @param <R>
     * @return
     */
    protected static <T, R> T requestMethodBodyBean(String appId, String apiUrl, R requestData, Class<T> responseBeanClass, RestTemplate restTemplate, HttpMethod httpMethod) {

        Object responseData = requestMethodBody(appId, apiUrl, requestData, restTemplate, httpMethod);
        if (responseData == null) {
            return null;
        }
        Map<String, Object> data = (Map<String, Object>) responseData;

        T responseInfoBean = null;
        try {
            responseInfoBean = BeanUtil.mapToBean(data, responseBeanClass, false);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("类型转换异常，map投射Bean异常:{}", e);
            throw new ClassCastException("类型转换异常，map投射Bean异常");
        }
        return responseInfoBean;
    }

    /**
     * 抽取请求beanList
     *
     * @param responseDataList
     * @param responseBeanClass
     * @param <T>
     * @param <R>
     * @return
     */
    protected static <T, R> List<T> requestMethodBodyBeanList(Collection<Object> responseDataList, Class<T> responseBeanClass) {

        try {
            return responseDataList.stream()
                    .map(responseData -> {
                        Map<String, Object> mapData = (Map<String, Object>) responseData;

                        return BeanUtil.mapToBean(mapData, responseBeanClass, false);
                    }).collect(Collectors.toList());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("类型转换异常，map投射Bean异常:{}", e);
            throw new ClassCastException("类型转换异常，map投射Bean异常");
        }
    }

    /**
     * 抽取请求body
     *
     * @param appId
     * @param apiUrl
     * @param requestData
     * @param restTemplate
     * @param httpMethod
     * @param <R>
     * @return
     */
    protected static <R> Object requestMethodBody(String appId, String apiUrl, R requestData, RestTemplate restTemplate, HttpMethod httpMethod) {

        String url = urlCreat(appId, apiUrl);
        RequestEntity<R> requestEntity = null;
        if (requestData == null) {
            requestEntity = new RequestEntity<>(httpMethod, URI.create(url));
        } else {
            requestEntity = new RequestEntity<>(requestData, httpMethod, URI.create(url));
        }
        // 这里的object可以替换成自己封装的返回类（更符合项目环境），小熙分享时是把项目中的替换成了object
        ResponseEntity<Object> exchange = null;
        try {
            exchange = restTemplate.exchange(requestEntity, Object.class);
        } catch (HttpClientErrorException e) {
            e.getResponseBodyAsString();
            log.error("HttpClientErrorException:{}", e);
            throw new RestClientException(e.getResponseBodyAsString());
        } catch (RestClientException e) {
            e.printStackTrace();
            log.error("RestTemplate远程调用请求异常:{}", e);
            throw new RestClientException("RestTemplate远程调用请求异常");
        }

        if (exchange == null) {
            log.info("exchange == null");
            return null;
        } else if (exchange.getBody() == null) {
            log.info("exchange.getBody() == null");
            return null;
        }
        return exchange.getBody();
    }

    /**
     * 抽取响应体的集合
     *
     * @param responseData
     * @param responseBeanClass
     * @param <T>
     * @return
     */
    protected static <T> List<T> getResponseDataList(Object responseData, Class<T> responseBeanClass) {
        if (responseData == null) {
            return null;
        }
        if (responseData instanceof Collection) {
            Collection<Object> responseDataList = (Collection<Object>) responseData;

            return requestMethodBodyBeanList(responseDataList, responseBeanClass);
        } else if (responseData.getClass().isArray()) {
            List<Object> responseDataList = Arrays.asList(responseData);

            return requestMethodBodyBeanList(responseDataList, responseBeanClass);
        }

        throw new ClassCastException("返回类型不是单链集合");
    }

    /**
     * 创建Url
     *
     * @param appId
     * @param apiUrl
     * @return
     */
    protected static String urlCreat(String appId, String apiUrl) {
        return "http://" + appId + apiUrl;
    }

}

